using System;

namespace Altova.Types
{
	public class Duration
	{
		protected TimeSpan myValue = new TimeSpan(0L);

		protected int months;

		protected int years;

		public TimeSpan Value
		{
			get
			{
				return myValue;
			}
			set
			{
				myValue = value;
			}
		}

		public int Years
		{
			get
			{
				return years;
			}
			set
			{
				years = value;
			}
		}

		public int Months
		{
			get
			{
				return months;
			}
			set
			{
				months = value;
			}
		}

		public Duration()
		{
		}

		public Duration(Duration obj)
		{
			myValue = obj.myValue;
			months = obj.months;
			years = obj.years;
		}

		public Duration(TimeSpan newvalue)
		{
			myValue = newvalue;
		}

		public Duration(long ticks)
		{
			myValue = new TimeSpan(ticks);
		}

		public Duration(int newyears, int newmonths, int days, int hours, int minutes, int seconds, double partseconds, bool bnegative)
		{
			years = newyears;
			months = newmonths;
			myValue = new TimeSpan(days, hours, minutes, seconds, (int)(partseconds * 1000.0));
			if (bnegative)
			{
				myValue = -myValue;
				years = -years;
				months = -months;
			}
		}

		public static Duration Parse(string s)
		{
			string text = s.Trim();
			Duration duration = new Duration();
			if (text == null || text.Length == 0)
			{
				throw new StringParseException("Duration must start with P or -P followed by a duration value.");
			}
			int num = 0;
			bool flag = false;
			int days = 0;
			int hours = 0;
			int minutes = 0;
			int seconds = 0;
			double num2 = 0.0;
			duration.months = 0;
			duration.years = 0;
			if (text[num] == '-')
			{
				flag = true;
				num++;
			}
			if (num == text.Length || text[num] != 'P')
			{
				throw new StringParseException("Duration must start with P or -P followed by a duration value.");
			}
			num++;
			int num3 = 0;
			while (num != text.Length)
			{
				if (num3 == 8)
				{
					throw new StringParseException("Extra data after duration value.");
				}
				if (text[num] == 'T')
				{
					if (num3 >= 4)
					{
						throw new StringParseException("Multiple Ts inside duration value.");
					}
					num3 = 4;
					num++;
				}
				if (num3 == 3)
				{
					throw new StringParseException("Extra data after duration value.");
				}
				if (num == text.Length || text[num] < '0' || text[num] > '9')
				{
					throw new StringParseException("Invalid numeric data in duration value.");
				}
				int num4 = 0;
				int num5 = 0;
				for (; num != text.Length && text[num] >= '0' && text[num] <= '9'; num++)
				{
					if (num4 >= 100000000)
					{
						throw new StringParseException("Numeric overflow in duration value.");
					}
					num4 = num4 * 10 + (text[num] - 48);
					num5++;
				}
				if (num == text.Length)
				{
					throw new StringParseException("Duration value missing component designator.");
				}
				int num6 = 8;
				switch (text[num])
				{
				case 'Y':
					num6 = ((num3 >= 4) ? 8 : 0);
					break;
				case 'M':
					num6 = ((num3 < 4) ? 1 : 5);
					break;
				case 'D':
					num6 = ((num3 < 4) ? 2 : 8);
					break;
				case 'H':
					num6 = ((num3 < 4) ? 8 : 4);
					break;
				case 'S':
					num6 = ((num3 < 7) ? ((num3 < 4) ? 8 : 6) : 7);
					break;
				case '.':
					num6 = ((num3 < 4) ? 8 : 6);
					break;
				}
				if (num6 == 8 || num6 < num3)
				{
					throw new StringParseException("Invalid or duplicate component designator.");
				}
				num++;
				switch (num6)
				{
				case 0:
					duration.years = num4;
					break;
				case 1:
					duration.months = num4;
					break;
				case 2:
					days = num4;
					break;
				case 4:
					hours = num4;
					break;
				case 5:
					minutes = num4;
					break;
				case 6:
					seconds = num4;
					break;
				case 7:
					num2 = (double)num4 * Math.Pow(0.1, num5);
					break;
				}
				num3 = num6 + 1;
			}
			if (num3 == 0)
			{
				throw new StringParseException("No components given after P in duration value.");
			}
			duration.myValue = new TimeSpan(days, hours, minutes, seconds, (int)(num2 * 1000.0));
			if (flag)
			{
				duration.myValue = -duration.myValue;
				duration.years = -duration.years;
				duration.months = -duration.months;
			}
			return duration;
		}

		public override bool Equals(object other)
		{
			Duration duration = other as Duration;
			if (object.ReferenceEquals(duration, null))
			{
				return false;
			}
			if (duration.years == years && duration.months == months)
			{
				return duration.myValue == myValue;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return years.GetHashCode() ^ months.GetHashCode() ^ myValue.GetHashCode();
		}

		public static bool operator ==(Duration a, Duration b)
		{
			if (object.ReferenceEquals(a, null))
			{
				return object.ReferenceEquals(b, null);
			}
			return a.Equals(b);
		}

		public static bool operator !=(Duration a, Duration b)
		{
			return !(a == b);
		}

		public override string ToString()
		{
			string text = "";
			if (myValue.Ticks < 0 || months < 0 || years < 0)
			{
				text += "-";
			}
			text += "P";
			if (years != 0)
			{
				text = text + Math.Abs(years) + "Y";
			}
			if (months != 0)
			{
				text = text + Math.Abs(months) + "M";
			}
			if (myValue.Days != 0)
			{
				text = text + Math.Abs(myValue.Days) + "D";
			}
			double num = (double)Math.Abs(myValue.Ticks) / 10000000.0 % 1.0;
			if (myValue.Hours != 0 || myValue.Minutes != 0 || myValue.Seconds != 0 || num > 0.0)
			{
				text += "T";
				if (myValue.Hours != 0)
				{
					text = text + Math.Abs(myValue.Hours) + "H";
				}
				if (myValue.Minutes != 0)
				{
					text = text + Math.Abs(myValue.Minutes) + "M";
				}
				if (myValue.Seconds != 0)
				{
					text += Math.Abs(myValue.Seconds).ToString("#0");
				}
				if (num > 0.0 && num < 1.0)
				{
					string text2 = num.ToString("0.##########");
					text = text + "." + text2.Substring(2, text2.Length - 2);
				}
				if (myValue.Seconds != 0 || (num > 0.0 && num < 1.0))
				{
					text += "S";
				}
			}
			if (text[text.Length - 1] == 'P')
			{
				text += "T0S";
			}
			return text;
		}

		public bool IsNegative()
		{
			return myValue.Ticks < 0;
		}
	}
}
